<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .tree-node {
        padding: 0;
        cursor: pointer;
      }

      .tree-node:hover {
        background-color: #f0f0f0;
      }

      .tree-node.selected {
        background-color: #c0c0c0;
      }

      .indent {
        /* width: 20px; */
        display: inline-block;
      }

      .switcher {
        width: 20px;
        display: inline-block;
      }

      .checkbox {
        width: 20px;
        display: inline-block;
      }

      .content {
        width: 200px;
        display: inline-block;
      }
    </style>
  </head>

  <body>
    <div id="tree-root"></div>

    <script>
      class TreeNode {
        constructor(title, children = []) {
          this.title = title;
          this.children = children;
          this.isExpanded = false;
          this.isSelected = false;
        }

        render() {
          const div = document.createElement("div");
          div.classList.add("tree-node");
          if (this.isSelected) {
            div.classList.add("selected");
          }

          const indent = document.createElement("div");
          indent.classList.add("indent");
          indent.innerHTML = "&nbsp;".repeat(this.getIndentLevel() * 2);
          div.appendChild(indent);

          const switcher = document.createElement("div");
          switcher.classList.add("switcher");
          switcher.innerHTML = this.isExpanded ? "-" : "+";
          switcher.addEventListener("click", () => {
            this.toggleExpand();
            this.renderChildren(div);
          });
          div.appendChild(switcher);

          const checkbox = document.createElement("div");
          checkbox.classList.add("checkbox");
          checkbox.innerHTML = this.isSelected ? "✔" : "❌";
          checkbox.addEventListener("click", () => {
            this.toggleSelect();
          });
          div.appendChild(checkbox);

          const content = document.createElement("div");
          content.classList.add("content");
          content.innerHTML = this.title;
          content.addEventListener("click", () => {
            this.onSelect();
          });
          div.appendChild(content);

          if (this.isExpanded) {
            this.renderChildren(div);
          }

          return div;
        }

        getIndentLevel() {
          let parent = this.parent;
          let level = 0;
          while (parent) {
            level++;
            parent = parent.parent;
          }
          return level;
        }

        toggleExpand() {
          this.isExpanded = !this.isExpanded;
        }

        toggleSelect() {
          this.isSelected = !this.isSelected;
        }

        onSelect() {
          console.log(`Selected: ${this.title}`);
        }

        renderChildren(parentDiv) {
          const childrenDiv = document.createElement("div");
          for (const child of this.children) {
            childrenDiv.appendChild(child.render());
          }
          parentDiv.appendChild(childrenDiv);
        }
      }

      const root = new TreeNode("Root", [
        new TreeNode("Child 1"),
        new TreeNode("Child 2", [
          new TreeNode("Grandchild 1"),
          new TreeNode("Grandchild 2"),
        ]),
      ]);

      document.getElementById("tree-root").appendChild(root.render());
    </script>
  </body>
</html>
